package org.jaronsource.framework.util;

import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Date;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.util.CycleDetectionStrategy;

import org.apache.commons.lang.StringUtils;
import org.codehaus.jackson.map.ObjectMapper;

public class JsonUtils {

	public static final ObjectMapper JACKSON_MAPPER = new ObjectMapper();

	public static String jacksonToJson( Object obj ) {
		String json = StringUtils.EMPTY;
		if ( obj != null ) {
			try {
				json = JACKSON_MAPPER.writeValueAsString( obj );
			}
			catch ( Exception e ) {}
		}
		return json;
	}

	@SuppressWarnings ( "rawtypes")
	public static String toJson( Object obj ) {
		String json = StringUtils.EMPTY;
		JsonConfig jsonConfig = new JsonConfig();
		jsonConfig.setCycleDetectionStrategy( CycleDetectionStrategy.LENIENT );
		jsonConfig.registerJsonValueProcessor( Date.class, new DateJsonValueProcessor( DateUtils.PATTERN_DATETIME_EXT ) );
		jsonConfig.setExcludes( new String[] { "handler", "hibernateLazyInitializer" } );
		if ( obj != null ) {
			if ( obj instanceof Collection ) {
				JSONArray jsonArray = new JSONArray();
				for ( Object objElement : (Collection) obj ) {
					JSONObject jsonObject = JSONObject.fromObject( objElement, jsonConfig );
					jsonArray.add( jsonObject );
				}
				json = jsonArray.toString();
			}
			else {
				json = JSONObject.fromObject( obj, jsonConfig ).toString();
			}
		}
		return json;
	}

	@SuppressWarnings ( "unchecked")
	public static <T> T fromJson( String jsonStr, Class<T> clazz ) {
		T result = null;
		JSONObject json = JSONObject.fromObject( jsonStr );
		try {
			result = (T) JSONObject.toBean( json, clazz );
		}
		catch ( Exception e ) {}
		return result;
	}

	public static void addElement(	JSONObject jsonObject,
									Object source,
									String pattern,
									String elementName ) {
		String[] patternFrags = StringUtils.split( pattern, "." );
		Object obj = source;
		Class<?> clazz = source.getClass();

		for ( String patternFrag : patternFrags ) {
			try {
				if ( obj != null ) {
					Field field = clazz.getDeclaredField( patternFrag );
					field.setAccessible( true );
					Object value = field.get( obj );
					obj = value;
					jsonObject.element( elementName, value );
				}
				else {
					break;
				}
			}
			catch ( Exception e ) {
				obj = null;
				break;
			}
		}
	}
}
